/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.10.0 (2021-10-11)
 */
(function() {
  'use strict'

  var global$7 = tinymce.util.Tools.resolve('tinymce.PluginManager')

  var typeOf = function(x) {
    var t = typeof x
    if (x === null) {
      return 'null'
    } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
      return 'array'
    } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
      return 'string'
    } else {
      return t
    }
  }
  var isType$1 = function(type) {
    return function(value) {
      return typeOf(value) === type
    }
  }
  var isSimpleType = function(type) {
    return function(value) {
      return typeof value === type
    }
  }
  var isString = isType$1('string')
  var isObject = isType$1('object')
  var isArray = isType$1('array')
  var isBoolean = isSimpleType('boolean')
  var isFunction = isSimpleType('function')
  var isNumber = isSimpleType('number')

  var noop = function() {
  }
  var constant = function(value) {
    return function() {
      return value
    }
  }
  var identity = function(x) {
    return x
  }
  var tripleEquals = function(a, b) {
    return a === b
  }
  var not = function(f) {
    return function(t) {
      return !f(t)
    }
  }
  var never = constant(false)
  var always = constant(true)

  var none = function() {
    return NONE
  }
  var NONE = (function() {
    var call = function(thunk) {
      return thunk()
    }
    var id = identity
    var me = {
      fold: function(n, _s) {
        return n()
      },
      isSome: never,
      isNone: always,
      getOr: id,
      getOrThunk: call,
      getOrDie: function(msg) {
        throw new Error(msg || 'error: getOrDie called on none.')
      },
      getOrNull: constant(null),
      getOrUndefined: constant(undefined),
      or: id,
      orThunk: call,
      map: none,
      each: noop,
      bind: none,
      exists: never,
      forall: always,
      filter: function() {
        return none()
      },
      toArray: function() {
        return []
      },
      toString: constant('none()')
    }
    return me
  }())
  var some = function(a) {
    var constant_a = constant(a)
    var self = function() {
      return me
    }
    var bind = function(f) {
      return f(a)
    }
    var me = {
      fold: function(n, s) {
        return s(a)
      },
      isSome: always,
      isNone: never,
      getOr: constant_a,
      getOrThunk: constant_a,
      getOrDie: constant_a,
      getOrNull: constant_a,
      getOrUndefined: constant_a,
      or: self,
      orThunk: self,
      map: function(f) {
        return some(f(a))
      },
      each: function(f) {
        f(a)
      },
      bind: bind,
      exists: bind,
      forall: bind,
      filter: function(f) {
        return f(a) ? me : NONE
      },
      toArray: function() {
        return [a]
      },
      toString: function() {
        return 'some(' + a + ')'
      }
    }
    return me
  }
  var from = function(value) {
    return value === null || value === undefined ? NONE : some(value)
  }
  var Optional = {
    some: some,
    none: none,
    from: from
  }

  var nativeSlice = Array.prototype.slice
  var nativePush = Array.prototype.push
  var map = function(xs, f) {
    var len = xs.length
    var r = new Array(len)
    for (var i = 0;i < len;i++) {
      var x = xs[i]
      r[i] = f(x, i)
    }
    return r
  }
  var each$1 = function(xs, f) {
    for (var i = 0, len = xs.length;i < len;i++) {
      var x = xs[i]
      f(x, i)
    }
  }
  var filter$1 = function(xs, pred) {
    var r = []
    for (var i = 0, len = xs.length;i < len;i++) {
      var x = xs[i]
      if (pred(x, i)) {
        r.push(x)
      }
    }
    return r
  }
  var groupBy = function(xs, f) {
    if (xs.length === 0) {
      return []
    } else {
      var wasType = f(xs[0])
      var r = []
      var group = []
      for (var i = 0, len = xs.length;i < len;i++) {
        var x = xs[i]
        var type = f(x)
        if (type !== wasType) {
          r.push(group)
          group = []
        }
        wasType = type
        group.push(x)
      }
      if (group.length !== 0) {
        r.push(group)
      }
      return r
    }
  }
  var foldl = function(xs, f, acc) {
    each$1(xs, function(x, i) {
      acc = f(acc, x, i)
    })
    return acc
  }
  var findUntil = function(xs, pred, until) {
    for (var i = 0, len = xs.length;i < len;i++) {
      var x = xs[i]
      if (pred(x, i)) {
        return Optional.some(x)
      } else if (until(x, i)) {
        break
      }
    }
    return Optional.none()
  }
  var find$1 = function(xs, pred) {
    return findUntil(xs, pred, never)
  }
  var flatten = function(xs) {
    var r = []
    for (var i = 0, len = xs.length;i < len;++i) {
      if (!isArray(xs[i])) {
        throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs)
      }
      nativePush.apply(r, xs[i])
    }
    return r
  }
  var bind = function(xs, f) {
    return flatten(map(xs, f))
  }
  var reverse = function(xs) {
    var r = nativeSlice.call(xs, 0)
    r.reverse()
    return r
  }
  var get$1 = function(xs, i) {
    return i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none()
  }
  var head = function(xs) {
    return get$1(xs, 0)
  }
  var last = function(xs) {
    return get$1(xs, xs.length - 1)
  }
  var findMap = function(arr, f) {
    for (var i = 0;i < arr.length;i++) {
      var r = f(arr[i], i)
      if (r.isSome()) {
        return r
      }
    }
    return Optional.none()
  }

  var __assign = function() {
    __assign = Object.assign || function __assign(t) {
      for (var s, i = 1, n = arguments.length;i < n;i++) {
        s = arguments[i]
        for (var p in s) {
          if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p] }
        }
      }
      return t
    }
    return __assign.apply(this, arguments)
  }
  function __spreadArray(to, from, pack) {
    if (pack || arguments.length === 2) {
      for (var i = 0, l = from.length, ar;i < l;i++) {
        if (ar || !(i in from)) {
          if (!ar) { ar = Array.prototype.slice.call(from, 0, i) }
          ar[i] = from[i]
        }
      }
    }
    return to.concat(ar || Array.prototype.slice.call(from))
  }

  var cached = function(f) {
    var called = false
    var r
    return function() {
      var args = []
      for (var _i = 0;_i < arguments.length;_i++) {
        args[_i] = arguments[_i]
      }
      if (!called) {
        called = true
        r = f.apply(null, args)
      }
      return r
    }
  }

  var DeviceType = function(os, browser, userAgent, mediaMatch) {
    var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true
    var isiPhone = os.isiOS() && !isiPad
    var isMobile = os.isiOS() || os.isAndroid()
    var isTouch = isMobile || mediaMatch('(pointer:coarse)')
    var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)')
    var isPhone = isiPhone || isMobile && !isTablet
    var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false
    var isDesktop = !isPhone && !isTablet && !iOSwebview
    return {
      isiPad: constant(isiPad),
      isiPhone: constant(isiPhone),
      isTablet: constant(isTablet),
      isPhone: constant(isPhone),
      isTouch: constant(isTouch),
      isAndroid: os.isAndroid,
      isiOS: os.isiOS,
      isWebView: constant(iOSwebview),
      isDesktop: constant(isDesktop)
    }
  }

  var firstMatch = function(regexes, s) {
    for (var i = 0;i < regexes.length;i++) {
      var x = regexes[i]
      if (x.test(s)) {
        return x
      }
    }
    return undefined
  }
  var find = function(regexes, agent) {
    var r = firstMatch(regexes, agent)
    if (!r) {
      return {
        major: 0,
        minor: 0
      }
    }
    var group = function(i) {
      return Number(agent.replace(r, '$' + i))
    }
    return nu$2(group(1), group(2))
  }
  var detect$3 = function(versionRegexes, agent) {
    var cleanedAgent = String(agent).toLowerCase()
    if (versionRegexes.length === 0) {
      return unknown$2()
    }
    return find(versionRegexes, cleanedAgent)
  }
  var unknown$2 = function() {
    return nu$2(0, 0)
  }
  var nu$2 = function(major, minor) {
    return {
      major: major,
      minor: minor
    }
  }
  var Version = {
    nu: nu$2,
    detect: detect$3,
    unknown: unknown$2
  }

  var detectBrowser$1 = function(browsers, userAgentData) {
    return findMap(userAgentData.brands, function(uaBrand) {
      var lcBrand = uaBrand.brand.toLowerCase()
      return find$1(browsers, function(browser) {
        var _a
        return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase())
      }).map(function(info) {
        return {
          current: info.name,
          version: Version.nu(parseInt(uaBrand.version, 10), 0)
        }
      })
    })
  }

  var detect$2 = function(candidates, userAgent) {
    var agent = String(userAgent).toLowerCase()
    return find$1(candidates, function(candidate) {
      return candidate.search(agent)
    })
  }
  var detectBrowser = function(browsers, userAgent) {
    return detect$2(browsers, userAgent).map(function(browser) {
      var version = Version.detect(browser.versionRegexes, userAgent)
      return {
        current: browser.name,
        version: version
      }
    })
  }
  var detectOs = function(oses, userAgent) {
    return detect$2(oses, userAgent).map(function(os) {
      var version = Version.detect(os.versionRegexes, userAgent)
      return {
        current: os.name,
        version: version
      }
    })
  }

  var contains$1 = function(str, substr) {
    return str.indexOf(substr) !== -1
  }
  var blank = function(r) {
    return function(s) {
      return s.replace(r, '')
    }
  }
  var trim = blank(/^\s+|\s+$/g)
  var isNotEmpty = function(s) {
    return s.length > 0
  }
  var isEmpty$1 = function(s) {
    return !isNotEmpty(s)
  }

  var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/
  var checkContains = function(target) {
    return function(uastring) {
      return contains$1(uastring, target)
    }
  }
  var browsers = [
    {
      name: 'Edge',
      versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
      search: function(uastring) {
        return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit')
      }
    },
    {
      name: 'Chrome',
      brand: 'Chromium',
      versionRegexes: [
        /.*?chrome\/([0-9]+)\.([0-9]+).*/,
        normalVersionRegex
      ],
      search: function(uastring) {
        return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe')
      }
    },
    {
      name: 'IE',
      versionRegexes: [
        /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
        /.*?rv:([0-9]+)\.([0-9]+).*/
      ],
      search: function(uastring) {
        return contains$1(uastring, 'msie') || contains$1(uastring, 'trident')
      }
    },
    {
      name: 'Opera',
      versionRegexes: [
        normalVersionRegex,
        /.*?opera\/([0-9]+)\.([0-9]+).*/
      ],
      search: checkContains('opera')
    },
    {
      name: 'Firefox',
      versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
      search: checkContains('firefox')
    },
    {
      name: 'Safari',
      versionRegexes: [
        normalVersionRegex,
        /.*?cpu os ([0-9]+)_([0-9]+).*/
      ],
      search: function(uastring) {
        return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit')
      }
    }
  ]
  var oses = [
    {
      name: 'Windows',
      search: checkContains('win'),
      versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
    },
    {
      name: 'iOS',
      search: function(uastring) {
        return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad')
      },
      versionRegexes: [
        /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
        /.*cpu os ([0-9]+)_([0-9]+).*/,
        /.*cpu iphone os ([0-9]+)_([0-9]+).*/
      ]
    },
    {
      name: 'Android',
      search: checkContains('android'),
      versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
    },
    {
      name: 'OSX',
      search: checkContains('mac os x'),
      versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
    },
    {
      name: 'Linux',
      search: checkContains('linux'),
      versionRegexes: []
    },
    {
      name: 'Solaris',
      search: checkContains('sunos'),
      versionRegexes: []
    },
    {
      name: 'FreeBSD',
      search: checkContains('freebsd'),
      versionRegexes: []
    },
    {
      name: 'ChromeOS',
      search: checkContains('cros'),
      versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
    }
  ]
  var PlatformInfo = {
    browsers: constant(browsers),
    oses: constant(oses)
  }

  var edge = 'Edge'
  var chrome = 'Chrome'
  var ie = 'IE'
  var opera = 'Opera'
  var firefox = 'Firefox'
  var safari = 'Safari'
  var unknown$1 = function() {
    return nu$1({
      current: undefined,
      version: Version.unknown()
    })
  }
  var nu$1 = function(info) {
    var current = info.current
    var version = info.version
    var isBrowser = function(name) {
      return function() {
        return current === name
      }
    }
    return {
      current: current,
      version: version,
      isEdge: isBrowser(edge),
      isChrome: isBrowser(chrome),
      isIE: isBrowser(ie),
      isOpera: isBrowser(opera),
      isFirefox: isBrowser(firefox),
      isSafari: isBrowser(safari)
    }
  }
  var Browser = {
    unknown: unknown$1,
    nu: nu$1,
    edge: constant(edge),
    chrome: constant(chrome),
    ie: constant(ie),
    opera: constant(opera),
    firefox: constant(firefox),
    safari: constant(safari)
  }

  var windows = 'Windows'
  var ios = 'iOS'
  var android = 'Android'
  var linux = 'Linux'
  var osx = 'OSX'
  var solaris = 'Solaris'
  var freebsd = 'FreeBSD'
  var chromeos = 'ChromeOS'
  var unknown = function() {
    return nu({
      current: undefined,
      version: Version.unknown()
    })
  }
  var nu = function(info) {
    var current = info.current
    var version = info.version
    var isOS = function(name) {
      return function() {
        return current === name
      }
    }
    return {
      current: current,
      version: version,
      isWindows: isOS(windows),
      isiOS: isOS(ios),
      isAndroid: isOS(android),
      isOSX: isOS(osx),
      isLinux: isOS(linux),
      isSolaris: isOS(solaris),
      isFreeBSD: isOS(freebsd),
      isChromeOS: isOS(chromeos)
    }
  }
  var OperatingSystem = {
    unknown: unknown,
    nu: nu,
    windows: constant(windows),
    ios: constant(ios),
    android: constant(android),
    linux: constant(linux),
    osx: constant(osx),
    solaris: constant(solaris),
    freebsd: constant(freebsd),
    chromeos: constant(chromeos)
  }

  var detect$1 = function(userAgent, userAgentDataOpt, mediaMatch) {
    var browsers = PlatformInfo.browsers()
    var oses = PlatformInfo.oses()
    var browser = userAgentDataOpt.bind(function(userAgentData) {
      return detectBrowser$1(browsers, userAgentData)
    }).orThunk(function() {
      return detectBrowser(browsers, userAgent)
    }).fold(Browser.unknown, Browser.nu)
    var os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu)
    var deviceType = DeviceType(os, browser, userAgent, mediaMatch)
    return {
      browser: browser,
      os: os,
      deviceType: deviceType
    }
  }
  var PlatformDetection = { detect: detect$1 }

  var mediaMatch = function(query) {
    return window.matchMedia(query).matches
  }
  var platform = cached(function() {
    return PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch)
  })
  var detect = function() {
    return platform()
  }

  var compareDocumentPosition = function(a, b, match) {
    return (a.compareDocumentPosition(b) & match) !== 0
  }
  var documentPositionContainedBy = function(a, b) {
    return compareDocumentPosition(a, b, Node.DOCUMENT_POSITION_CONTAINED_BY)
  }

  var ELEMENT = 1

  var fromHtml = function(html, scope) {
    var doc = scope || document
    var div = doc.createElement('div')
    div.innerHTML = html
    if (!div.hasChildNodes() || div.childNodes.length > 1) {
      console.error('HTML does not have a single root node', html)
      throw new Error('HTML must have a single root node')
    }
    return fromDom(div.childNodes[0])
  }
  var fromTag = function(tag, scope) {
    var doc = scope || document
    var node = doc.createElement(tag)
    return fromDom(node)
  }
  var fromText = function(text, scope) {
    var doc = scope || document
    var node = doc.createTextNode(text)
    return fromDom(node)
  }
  var fromDom = function(node) {
    if (node === null || node === undefined) {
      throw new Error('Node cannot be null or undefined')
    }
    return { dom: node }
  }
  var fromPoint = function(docElm, x, y) {
    return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom)
  }
  var SugarElement = {
    fromHtml: fromHtml,
    fromTag: fromTag,
    fromText: fromText,
    fromDom: fromDom,
    fromPoint: fromPoint
  }

  var is$2 = function(element, selector) {
    var dom = element.dom
    if (dom.nodeType !== ELEMENT) {
      return false
    } else {
      var elem = dom
      if (elem.matches !== undefined) {
        return elem.matches(selector)
      } else if (elem.msMatchesSelector !== undefined) {
        return elem.msMatchesSelector(selector)
      } else if (elem.webkitMatchesSelector !== undefined) {
        return elem.webkitMatchesSelector(selector)
      } else if (elem.mozMatchesSelector !== undefined) {
        return elem.mozMatchesSelector(selector)
      } else {
        throw new Error('Browser lacks native selectors')
      }
    }
  }

  var eq = function(e1, e2) {
    return e1.dom === e2.dom
  }
  var regularContains = function(e1, e2) {
    var d1 = e1.dom
    var d2 = e2.dom
    return d1 === d2 ? false : d1.contains(d2)
  }
  var ieContains = function(e1, e2) {
    return documentPositionContainedBy(e1.dom, e2.dom)
  }
  var contains = function(e1, e2) {
    return detect().browser.isIE() ? ieContains(e1, e2) : regularContains(e1, e2)
  }
  var is$1 = is$2

  var global$6 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils')

  var global$5 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker')

  var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK')

  var keys = Object.keys
  var each = function(obj, f) {
    var props = keys(obj)
    for (var k = 0, len = props.length;k < len;k++) {
      var i = props[k]
      var x = obj[i]
      f(x, i)
    }
  }
  var objAcc = function(r) {
    return function(x, i) {
      r[i] = x
    }
  }
  var internalFilter = function(obj, pred, onTrue, onFalse) {
    var r = {}
    each(obj, function(x, i) {
      (pred(x, i) ? onTrue : onFalse)(x, i)
    })
    return r
  }
  var filter = function(obj, pred) {
    var t = {}
    internalFilter(obj, pred, objAcc(t), noop)
    return t
  }

  typeof window !== 'undefined' ? window : Function('return this;')()

  var name = function(element) {
    var r = element.dom.nodeName
    return r.toLowerCase()
  }
  var type = function(element) {
    return element.dom.nodeType
  }
  var isType = function(t) {
    return function(element) {
      return type(element) === t
    }
  }
  var isElement = isType(ELEMENT)
  var isTag = function(tag) {
    return function(e) {
      return isElement(e) && name(e) === tag
    }
  }

  var rawSet = function(dom, key, value) {
    if (isString(value) || isBoolean(value) || isNumber(value)) {
      dom.setAttribute(key, value + '')
    } else {
      console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom)
      throw new Error('Attribute value was not simple')
    }
  }
  var setAll = function(element, attrs) {
    var dom = element.dom
    each(attrs, function(v, k) {
      rawSet(dom, k, v)
    })
  }
  var clone$1 = function(element) {
    return foldl(element.dom.attributes, function(acc, attr) {
      acc[attr.name] = attr.value
      return acc
    }, {})
  }

  var parent = function(element) {
    return Optional.from(element.dom.parentNode).map(SugarElement.fromDom)
  }
  var children = function(element) {
    return map(element.dom.childNodes, SugarElement.fromDom)
  }
  var child = function(element, index) {
    var cs = element.dom.childNodes
    return Optional.from(cs[index]).map(SugarElement.fromDom)
  }
  var firstChild = function(element) {
    return child(element, 0)
  }
  var lastChild = function(element) {
    return child(element, element.dom.childNodes.length - 1)
  }

  var before$1 = function(marker, element) {
    var parent$1 = parent(marker)
    parent$1.each(function(v) {
      v.dom.insertBefore(element.dom, marker.dom)
    })
  }
  var append$1 = function(parent, element) {
    parent.dom.appendChild(element.dom)
  }

  var before = function(marker, elements) {
    each$1(elements, function(x) {
      before$1(marker, x)
    })
  }
  var append = function(parent, elements) {
    each$1(elements, function(x) {
      append$1(parent, x)
    })
  }

  var remove = function(element) {
    var dom = element.dom
    if (dom.parentNode !== null) {
      dom.parentNode.removeChild(dom)
    }
  }

  var clone = function(original, isDeep) {
    return SugarElement.fromDom(original.dom.cloneNode(isDeep))
  }
  var deep = function(original) {
    return clone(original, true)
  }
  var shallowAs = function(original, tag) {
    var nu = SugarElement.fromTag(tag)
    var attributes = clone$1(original)
    setAll(nu, attributes)
    return nu
  }
  var mutate = function(original, tag) {
    var nu = shallowAs(original, tag)
    before$1(original, nu)
    var children$1 = children(original)
    append(nu, children$1)
    remove(original)
    return nu
  }

  var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils')

  var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools')

  var matchNodeName = function(name) {
    return function(node) {
      return node && node.nodeName.toLowerCase() === name
    }
  }
  var matchNodeNames = function(regex) {
    return function(node) {
      return node && regex.test(node.nodeName)
    }
  }
  var isTextNode = function(node) {
    return node && node.nodeType === 3
  }
  var isListNode = matchNodeNames(/^(OL|UL|DL)$/)
  var isOlUlNode = matchNodeNames(/^(OL|UL)$/)
  var isOlNode = matchNodeName('ol')
  var isListItemNode = matchNodeNames(/^(LI|DT|DD)$/)
  var isDlItemNode = matchNodeNames(/^(DT|DD)$/)
  var isTableCellNode = matchNodeNames(/^(TH|TD)$/)
  var isBr = matchNodeName('br')
  var isFirstChild = function(node) {
    return node.parentNode.firstChild === node
  }
  var isTextBlock = function(editor, node) {
    return node && !!editor.schema.getTextBlockElements()[node.nodeName]
  }
  var isBlock = function(node, blockElements) {
    return node && node.nodeName in blockElements
  }
  var isBogusBr = function(dom, node) {
    if (!isBr(node)) {
      return false
    }
    return dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)
  }
  var isEmpty = function(dom, elm, keepBookmarks) {
    var empty = dom.isEmpty(elm)
    if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
      return false
    }
    return empty
  }
  var isChildOfBody = function(dom, elm) {
    return dom.isChildOf(elm, dom.getRoot())
  }

  var shouldIndentOnTab = function(editor) {
    return editor.getParam('lists_indent_on_tab', true)
  }
  var getForcedRootBlock = function(editor) {
    var block = editor.getParam('forced_root_block', 'p')
    if (block === false) {
      return ''
    } else if (block === true) {
      return 'p'
    } else {
      return block
    }
  }
  var getForcedRootBlockAttrs = function(editor) {
    return editor.getParam('forced_root_block_attrs', {})
  }

  var createTextBlock = function(editor, contentNode) {
    var dom = editor.dom
    var blockElements = editor.schema.getBlockElements()
    var fragment = dom.createFragment()
    var blockName = getForcedRootBlock(editor)
    var node, textBlock, hasContentNode
    if (blockName) {
      textBlock = dom.create(blockName)
      if (textBlock.tagName === blockName.toUpperCase()) {
        dom.setAttribs(textBlock, getForcedRootBlockAttrs(editor))
      }
      if (!isBlock(contentNode.firstChild, blockElements)) {
        fragment.appendChild(textBlock)
      }
    }
    if (contentNode) {
      while (node = contentNode.firstChild) {
        var nodeName = node.nodeName
        if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
          hasContentNode = true
        }
        if (isBlock(node, blockElements)) {
          fragment.appendChild(node)
          textBlock = null
        } else {
          if (blockName) {
            if (!textBlock) {
              textBlock = dom.create(blockName)
              fragment.appendChild(textBlock)
            }
            textBlock.appendChild(node)
          } else {
            fragment.appendChild(node)
          }
        }
      }
    }
    if (!blockName) {
      fragment.appendChild(dom.create('br'))
    } else {
      if (!hasContentNode) {
        textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' }))
      }
    }
    return fragment
  }

  var DOM$2 = global$3.DOM
  var splitList = function(editor, list, li) {
    var removeAndKeepBookmarks = function(targetNode) {
      global$2.each(bookmarks, function(node) {
        targetNode.parentNode.insertBefore(node, li.parentNode)
      })
      DOM$2.remove(targetNode)
    }
    var bookmarks = DOM$2.select('span[data-mce-type="bookmark"]', list)
    var newBlock = createTextBlock(editor, li)
    var tmpRng = DOM$2.createRng()
    tmpRng.setStartAfter(li)
    tmpRng.setEndAfter(list)
    var fragment = tmpRng.extractContents()
    for (var node = fragment.firstChild;node;node = node.firstChild) {
      if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
        DOM$2.remove(node)
        break
      }
    }
    if (!editor.dom.isEmpty(fragment)) {
      DOM$2.insertAfter(fragment, list)
    }
    DOM$2.insertAfter(newBlock, list)
    if (isEmpty(editor.dom, li.parentNode)) {
      removeAndKeepBookmarks(li.parentNode)
    }
    DOM$2.remove(li)
    if (isEmpty(editor.dom, list)) {
      DOM$2.remove(list)
    }
  }

  var isDescriptionDetail = isTag('dd')
  var isDescriptionTerm = isTag('dt')
  var outdentDlItem = function(editor, item) {
    if (isDescriptionDetail(item)) {
      mutate(item, 'dt')
    } else if (isDescriptionTerm(item)) {
      parent(item).each(function(dl) {
        return splitList(editor, dl.dom, item.dom)
      })
    }
  }
  var indentDlItem = function(item) {
    if (isDescriptionTerm(item)) {
      mutate(item, 'dd')
    }
  }
  var dlIndentation = function(editor, indentation, dlItems) {
    if (indentation === 'Indent') {
      each$1(dlItems, indentDlItem)
    } else {
      each$1(dlItems, function(item) {
        return outdentDlItem(editor, item)
      })
    }
  }

  var getNormalizedPoint = function(container, offset) {
    if (isTextNode(container)) {
      return {
        container: container,
        offset: offset
      }
    }
    var node = global$6.getNode(container, offset)
    if (isTextNode(node)) {
      return {
        container: node,
        offset: offset >= container.childNodes.length ? node.data.length : 0
      }
    } else if (node.previousSibling && isTextNode(node.previousSibling)) {
      return {
        container: node.previousSibling,
        offset: node.previousSibling.data.length
      }
    } else if (node.nextSibling && isTextNode(node.nextSibling)) {
      return {
        container: node.nextSibling,
        offset: 0
      }
    }
    return {
      container: container,
      offset: offset
    }
  }
  var normalizeRange = function(rng) {
    var outRng = rng.cloneRange()
    var rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset)
    outRng.setStart(rangeStart.container, rangeStart.offset)
    var rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset)
    outRng.setEnd(rangeEnd.container, rangeEnd.offset)
    return outRng
  }

  var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DomQuery')

  var getParentList = function(editor, node) {
    var selectionStart = node || editor.selection.getStart(true)
    return editor.dom.getParent(selectionStart, 'OL,UL,DL', getClosestListRootElm(editor, selectionStart))
  }
  var isParentListSelected = function(parentList, selectedBlocks) {
    return parentList && selectedBlocks.length === 1 && selectedBlocks[0] === parentList
  }
  var findSubLists = function(parentList) {
    return filter$1(parentList.querySelectorAll('ol,ul,dl'), isListNode)
  }
  var getSelectedSubLists = function(editor) {
    var parentList = getParentList(editor)
    var selectedBlocks = editor.selection.getSelectedBlocks()
    if (isParentListSelected(parentList, selectedBlocks)) {
      return findSubLists(parentList)
    } else {
      return filter$1(selectedBlocks, function(elm) {
        return isListNode(elm) && parentList !== elm
      })
    }
  }
  var findParentListItemsNodes = function(editor, elms) {
    var listItemsElms = global$2.map(elms, function(elm) {
      var parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListRootElm(editor, elm))
      return parentLi || elm
    })
    return global$1.unique(listItemsElms)
  }
  var getSelectedListItems = function(editor) {
    var selectedBlocks = editor.selection.getSelectedBlocks()
    return filter$1(findParentListItemsNodes(editor, selectedBlocks), isListItemNode)
  }
  var getSelectedDlItems = function(editor) {
    return filter$1(getSelectedListItems(editor), isDlItemNode)
  }
  var getClosestListRootElm = function(editor, elm) {
    var parentTableCell = editor.dom.getParents(elm, 'TD,TH')
    return parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody()
  }
  var findLastParentListNode = function(editor, elm) {
    var parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListRootElm(editor, elm))
    return last(parentLists)
  }
  var getSelectedLists = function(editor) {
    var firstList = findLastParentListNode(editor, editor.selection.getStart())
    var subsequentLists = filter$1(editor.selection.getSelectedBlocks(), isOlUlNode)
    return firstList.toArray().concat(subsequentLists)
  }
  var getSelectedListRoots = function(editor) {
    var selectedLists = getSelectedLists(editor)
    return getUniqueListRoots(editor, selectedLists)
  }
  var getUniqueListRoots = function(editor, lists) {
    var listRoots = map(lists, function(list) {
      return findLastParentListNode(editor, list).getOr(list)
    })
    return global$1.unique(listRoots)
  }

  var is = function(lhs, rhs, comparator) {
    if (comparator === void 0) {
      comparator = tripleEquals
    }
    return lhs.exists(function(left) {
      return comparator(left, rhs)
    })
  }
  var lift2 = function(oa, ob, f) {
    return oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none()
  }

  var fromElements = function(elements, scope) {
    var doc = scope || document
    var fragment = doc.createDocumentFragment()
    each$1(elements, function(element) {
      fragment.appendChild(element.dom)
    })
    return SugarElement.fromDom(fragment)
  }

  var fireListEvent = function(editor, action, element) {
    return editor.fire('ListMutation', {
      action: action,
      element: element
    })
  }

  var isSupported = function(dom) {
    return dom.style !== undefined && isFunction(dom.style.getPropertyValue)
  }

  var internalSet = function(dom, property, value) {
    if (!isString(value)) {
      console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom)
      throw new Error('CSS value must be a string: ' + value)
    }
    if (isSupported(dom)) {
      dom.style.setProperty(property, value)
    }
  }
  var set = function(element, property, value) {
    var dom = element.dom
    internalSet(dom, property, value)
  }

  var joinSegment = function(parent, child) {
    append$1(parent.item, child.list)
  }
  var joinSegments = function(segments) {
    for (var i = 1;i < segments.length;i++) {
      joinSegment(segments[i - 1], segments[i])
    }
  }
  var appendSegments = function(head$1, tail) {
    lift2(last(head$1), head(tail), joinSegment)
  }
  var createSegment = function(scope, listType) {
    var segment = {
      list: SugarElement.fromTag(listType, scope),
      item: SugarElement.fromTag('li', scope)
    }
    append$1(segment.list, segment.item)
    return segment
  }
  var createSegments = function(scope, entry, size) {
    var segments = []
    for (var i = 0;i < size;i++) {
      segments.push(createSegment(scope, entry.listType))
    }
    return segments
  }
  var populateSegments = function(segments, entry) {
    for (var i = 0;i < segments.length - 1;i++) {
      set(segments[i].item, 'list-style-type', 'none')
    }
    last(segments).each(function(segment) {
      setAll(segment.list, entry.listAttributes)
      setAll(segment.item, entry.itemAttributes)
      append(segment.item, entry.content)
    })
  }
  var normalizeSegment = function(segment, entry) {
    if (name(segment.list) !== entry.listType) {
      segment.list = mutate(segment.list, entry.listType)
    }
    setAll(segment.list, entry.listAttributes)
  }
  var createItem = function(scope, attr, content) {
    var item = SugarElement.fromTag('li', scope)
    setAll(item, attr)
    append(item, content)
    return item
  }
  var appendItem = function(segment, item) {
    append$1(segment.list, item)
    segment.item = item
  }
  var writeShallow = function(scope, cast, entry) {
    var newCast = cast.slice(0, entry.depth)
    last(newCast).each(function(segment) {
      var item = createItem(scope, entry.itemAttributes, entry.content)
      appendItem(segment, item)
      normalizeSegment(segment, entry)
    })
    return newCast
  }
  var writeDeep = function(scope, cast, entry) {
    var segments = createSegments(scope, entry, entry.depth - cast.length)
    joinSegments(segments)
    populateSegments(segments, entry)
    appendSegments(cast, segments)
    return cast.concat(segments)
  }
  var composeList = function(scope, entries) {
    var cast = foldl(entries, function(cast, entry) {
      return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry)
    }, [])
    return head(cast).map(function(segment) {
      return segment.list
    })
  }

  var isList = function(el) {
    return is$1(el, 'OL,UL')
  }
  var hasFirstChildList = function(el) {
    return firstChild(el).exists(isList)
  }
  var hasLastChildList = function(el) {
    return lastChild(el).exists(isList)
  }

  var isIndented = function(entry) {
    return entry.depth > 0
  }
  var isSelected = function(entry) {
    return entry.isSelected
  }
  var cloneItemContent = function(li) {
    var children$1 = children(li)
    var content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1
    return map(content, deep)
  }
  var createEntry = function(li, depth, isSelected) {
    return parent(li).filter(isElement).map(function(list) {
      return {
        depth: depth,
        dirty: false,
        isSelected: isSelected,
        content: cloneItemContent(li),
        itemAttributes: clone$1(li),
        listAttributes: clone$1(list),
        listType: name(list)
      }
    })
  }

  var indentEntry = function(indentation, entry) {
    switch (indentation) {
      case 'Indent':
        entry.depth++
        break
      case 'Outdent':
        entry.depth--
        break
      case 'Flatten':
        entry.depth = 0
    }
    entry.dirty = true
  }

  var cloneListProperties = function(target, source) {
    target.listType = source.listType
    target.listAttributes = __assign({}, source.listAttributes)
  }
  var cleanListProperties = function(entry) {
    entry.listAttributes = filter(entry.listAttributes, function(_value, key) {
      return key !== 'start'
    })
  }
  var closestSiblingEntry = function(entries, start) {
    var depth = entries[start].depth
    var matches = function(entry) {
      return entry.depth === depth && !entry.dirty
    }
    var until = function(entry) {
      return entry.depth < depth
    }
    return findUntil(reverse(entries.slice(0, start)), matches, until).orThunk(function() {
      return findUntil(entries.slice(start + 1), matches, until)
    })
  }
  var normalizeEntries = function(entries) {
    each$1(entries, function(entry, i) {
      closestSiblingEntry(entries, i).fold(function() {
        if (entry.dirty) {
          cleanListProperties(entry)
        }
      }, function(matchingEntry) {
        return cloneListProperties(entry, matchingEntry)
      })
    })
    return entries
  }

  var Cell = function(initial) {
    var value = initial
    var get = function() {
      return value
    }
    var set = function(v) {
      value = v
    }
    return {
      get: get,
      set: set
    }
  }

  var parseItem = function(depth, itemSelection, selectionState, item) {
    return firstChild(item).filter(isList).fold(function() {
      itemSelection.each(function(selection) {
        if (eq(selection.start, item)) {
          selectionState.set(true)
        }
      })
      var currentItemEntry = createEntry(item, depth, selectionState.get())
      itemSelection.each(function(selection) {
        if (eq(selection.end, item)) {
          selectionState.set(false)
        }
      })
      var childListEntries = lastChild(item).filter(isList).map(function(list) {
        return parseList(depth, itemSelection, selectionState, list)
      }).getOr([])
      return currentItemEntry.toArray().concat(childListEntries)
    }, function(list) {
      return parseList(depth, itemSelection, selectionState, list)
    })
  }
  var parseList = function(depth, itemSelection, selectionState, list) {
    return bind(children(list), function(element) {
      var parser = isList(element) ? parseList : parseItem
      var newDepth = depth + 1
      return parser(newDepth, itemSelection, selectionState, element)
    })
  }
  var parseLists = function(lists, itemSelection) {
    var selectionState = Cell(false)
    var initialDepth = 0
    return map(lists, function(list) {
      return {
        sourceList: list,
        entries: parseList(initialDepth, itemSelection, selectionState, list)
      }
    })
  }

  var outdentedComposer = function(editor, entries) {
    var normalizedEntries = normalizeEntries(entries)
    return map(normalizedEntries, function(entry) {
      var content = fromElements(entry.content)
      return SugarElement.fromDom(createTextBlock(editor, content.dom))
    })
  }
  var indentedComposer = function(editor, entries) {
    var normalizedEntries = normalizeEntries(entries)
    return composeList(editor.contentDocument, normalizedEntries).toArray()
  }
  var composeEntries = function(editor, entries) {
    return bind(groupBy(entries, isIndented), function(entries) {
      var groupIsIndented = head(entries).exists(isIndented)
      return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries)
    })
  }
  var indentSelectedEntries = function(entries, indentation) {
    each$1(filter$1(entries, isSelected), function(entry) {
      return indentEntry(indentation, entry)
    })
  }
  var getItemSelection = function(editor) {
    var selectedListItems = map(getSelectedListItems(editor), SugarElement.fromDom)
    return lift2(find$1(selectedListItems, not(hasFirstChildList)), find$1(reverse(selectedListItems), not(hasFirstChildList)), function(start, end) {
      return {
        start: start,
        end: end
      }
    })
  }
  var listIndentation = function(editor, lists, indentation) {
    var entrySets = parseLists(lists, getItemSelection(editor))
    each$1(entrySets, function(entrySet) {
      indentSelectedEntries(entrySet.entries, indentation)
      var composedLists = composeEntries(editor, entrySet.entries)
      each$1(composedLists, function(composedList) {
        fireListEvent(editor, indentation === 'Indent' ? 'IndentList' : 'OutdentList', composedList.dom)
      })
      before(entrySet.sourceList, composedLists)
      remove(entrySet.sourceList)
    })
  }

  var selectionIndentation = function(editor, indentation) {
    var lists = map(getSelectedListRoots(editor), SugarElement.fromDom)
    var dlItems = map(getSelectedDlItems(editor), SugarElement.fromDom)
    var isHandled = false
    if (lists.length || dlItems.length) {
      var bookmark = editor.selection.getBookmark()
      listIndentation(editor, lists, indentation)
      dlIndentation(editor, indentation, dlItems)
      editor.selection.moveToBookmark(bookmark)
      editor.selection.setRng(normalizeRange(editor.selection.getRng()))
      editor.nodeChanged()
      isHandled = true
    }
    return isHandled
  }
  var indentListSelection = function(editor) {
    return selectionIndentation(editor, 'Indent')
  }
  var outdentListSelection = function(editor) {
    return selectionIndentation(editor, 'Outdent')
  }
  var flattenListSelection = function(editor) {
    return selectionIndentation(editor, 'Flatten')
  }

  var global = tinymce.util.Tools.resolve('tinymce.dom.BookmarkManager')

  var DOM$1 = global$3.DOM
  var createBookmark = function(rng) {
    var bookmark = {}
    var setupEndPoint = function(start) {
      var container = rng[start ? 'startContainer' : 'endContainer']
      var offset = rng[start ? 'startOffset' : 'endOffset']
      if (container.nodeType === 1) {
        var offsetNode = DOM$1.create('span', { 'data-mce-type': 'bookmark' })
        if (container.hasChildNodes()) {
          offset = Math.min(offset, container.childNodes.length - 1)
          if (start) {
            container.insertBefore(offsetNode, container.childNodes[offset])
          } else {
            DOM$1.insertAfter(offsetNode, container.childNodes[offset])
          }
        } else {
          container.appendChild(offsetNode)
        }
        container = offsetNode
        offset = 0
      }
      bookmark[start ? 'startContainer' : 'endContainer'] = container
      bookmark[start ? 'startOffset' : 'endOffset'] = offset
    }
    setupEndPoint(true)
    if (!rng.collapsed) {
      setupEndPoint()
    }
    return bookmark
  }
  var resolveBookmark = function(bookmark) {
    var restoreEndPoint = function(start) {
      var node
      var nodeIndex = function(container) {
        var node = container.parentNode.firstChild;var idx = 0
        while (node) {
          if (node === container) {
            return idx
          }
          if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') {
            idx++
          }
          node = node.nextSibling
        }
        return -1
      }
      var container = node = bookmark[start ? 'startContainer' : 'endContainer']
      var offset = bookmark[start ? 'startOffset' : 'endOffset']
      if (!container) {
        return
      }
      if (container.nodeType === 1) {
        offset = nodeIndex(container)
        container = container.parentNode
        DOM$1.remove(node)
        if (!container.hasChildNodes() && DOM$1.isBlock(container)) {
          container.appendChild(DOM$1.create('br'))
        }
      }
      bookmark[start ? 'startContainer' : 'endContainer'] = container
      bookmark[start ? 'startOffset' : 'endOffset'] = offset
    }
    restoreEndPoint(true)
    restoreEndPoint()
    var rng = DOM$1.createRng()
    rng.setStart(bookmark.startContainer, bookmark.startOffset)
    if (bookmark.endContainer) {
      rng.setEnd(bookmark.endContainer, bookmark.endOffset)
    }
    return normalizeRange(rng)
  }

  var listToggleActionFromListName = function(listName) {
    switch (listName) {
      case 'UL':
        return 'ToggleUlList'
      case 'OL':
        return 'ToggleOlList'
      case 'DL':
        return 'ToggleDLList'
    }
  }

  var isCustomList = function(list) {
    return /\btox\-/.test(list.className)
  }
  var listState = function(editor, listName, activate) {
    var nodeChangeHandler = function(e) {
      var inList = findUntil(e.parents, isListNode, isTableCellNode).filter(function(list) {
        return list.nodeName === listName && !isCustomList(list)
      }).isSome()
      activate(inList)
    }
    var parents = editor.dom.getParents(editor.selection.getNode())
    nodeChangeHandler({ parents: parents })
    editor.on('NodeChange', nodeChangeHandler)
    return function() {
      return editor.off('NodeChange', nodeChangeHandler)
    }
  }

  var updateListStyle = function(dom, el, detail) {
    var type = detail['list-style-type'] ? detail['list-style-type'] : null
    dom.setStyle(el, 'list-style-type', type)
  }
  var setAttribs = function(elm, attrs) {
    global$2.each(attrs, function(value, key) {
      elm.setAttribute(key, value)
    })
  }
  var updateListAttrs = function(dom, el, detail) {
    setAttribs(el, detail['list-attributes'])
    global$2.each(dom.select('li', el), function(li) {
      setAttribs(li, detail['list-item-attributes'])
    })
  }
  var updateListWithDetails = function(dom, el, detail) {
    updateListStyle(dom, el, detail)
    updateListAttrs(dom, el, detail)
  }
  var removeStyles = function(dom, element, styles) {
    global$2.each(styles, function(style) {
      var _a
      return dom.setStyle(element, (_a = {}, _a[style] = '', _a))
    })
  }
  var getEndPointNode = function(editor, rng, start, root) {
    var container = rng[start ? 'startContainer' : 'endContainer']
    var offset = rng[start ? 'startOffset' : 'endOffset']
    if (container.nodeType === 1) {
      container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container
    }
    if (!start && isBr(container.nextSibling)) {
      container = container.nextSibling
    }
    while (container.parentNode !== root) {
      if (isTextBlock(editor, container)) {
        return container
      }
      if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
        return container
      }
      container = container.parentNode
    }
    return container
  }
  var getSelectedTextBlocks = function(editor, rng, root) {
    var textBlocks = []
    var dom = editor.dom
    var startNode = getEndPointNode(editor, rng, true, root)
    var endNode = getEndPointNode(editor, rng, false, root)
    var block
    var siblings = []
    for (var node = startNode;node;node = node.nextSibling) {
      siblings.push(node)
      if (node === endNode) {
        break
      }
    }
    global$2.each(siblings, function(node) {
      if (isTextBlock(editor, node)) {
        textBlocks.push(node)
        block = null
        return
      }
      if (dom.isBlock(node) || isBr(node)) {
        if (isBr(node)) {
          dom.remove(node)
        }
        block = null
        return
      }
      var nextSibling = node.nextSibling
      if (global.isBookmarkNode(node)) {
        if (isListNode(nextSibling) || isTextBlock(editor, nextSibling) || !nextSibling && node.parentNode === root) {
          block = null
          return
        }
      }
      if (!block) {
        block = dom.create('p')
        node.parentNode.insertBefore(block, node)
        textBlocks.push(block)
      }
      block.appendChild(node)
    })
    return textBlocks
  }
  var hasCompatibleStyle = function(dom, sib, detail) {
    var sibStyle = dom.getStyle(sib, 'list-style-type')
    var detailStyle = detail ? detail['list-style-type'] : ''
    detailStyle = detailStyle === null ? '' : detailStyle
    return sibStyle === detailStyle
  }
  var applyList = function(editor, listName, detail) {
    var rng = editor.selection.getRng()
    var listItemName = 'LI'
    var root = getClosestListRootElm(editor, editor.selection.getStart(true))
    var dom = editor.dom
    if (dom.getContentEditable(editor.selection.getNode()) === 'false') {
      return
    }
    listName = listName.toUpperCase()
    if (listName === 'DL') {
      listItemName = 'DT'
    }
    var bookmark = createBookmark(rng)
    var selectedTextBlocks = getSelectedTextBlocks(editor, rng, root)
    global$2.each(selectedTextBlocks, function(block) {
      var listBlock
      var sibling = block.previousSibling
      var parent = block.parentNode
      if (!isListItemNode(parent)) {
        if (sibling && isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) {
          listBlock = sibling
          block = dom.rename(block, listItemName)
          sibling.appendChild(block)
        } else {
          listBlock = dom.create(listName)
          block.parentNode.insertBefore(listBlock, block)
          listBlock.appendChild(block)
          block = dom.rename(block, listItemName)
        }
        removeStyles(dom, block, [
          'margin',
          'margin-right',
          'margin-bottom',
          'margin-left',
          'margin-top',
          'padding',
          'padding-right',
          'padding-bottom',
          'padding-left',
          'padding-top'
        ])
        updateListWithDetails(dom, listBlock, detail)
        mergeWithAdjacentLists(editor.dom, listBlock)
      }
    })
    editor.selection.setRng(resolveBookmark(bookmark))
  }
  var isValidLists = function(list1, list2) {
    return list1 && list2 && isListNode(list1) && list1.nodeName === list2.nodeName
  }
  var hasSameListStyle = function(dom, list1, list2) {
    var targetStyle = dom.getStyle(list1, 'list-style-type', true)
    var style = dom.getStyle(list2, 'list-style-type', true)
    return targetStyle === style
  }
  var hasSameClasses = function(elm1, elm2) {
    return elm1.className === elm2.className
  }
  var shouldMerge = function(dom, list1, list2) {
    return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2)
  }
  var mergeWithAdjacentLists = function(dom, listBlock) {
    var sibling, node
    sibling = listBlock.nextSibling
    if (shouldMerge(dom, listBlock, sibling)) {
      while (node = sibling.firstChild) {
        listBlock.appendChild(node)
      }
      dom.remove(sibling)
    }
    sibling = listBlock.previousSibling
    if (shouldMerge(dom, listBlock, sibling)) {
      while (node = sibling.lastChild) {
        listBlock.insertBefore(node, listBlock.firstChild)
      }
      dom.remove(sibling)
    }
  }
  var updateList$1 = function(editor, list, listName, detail) {
    if (list.nodeName !== listName) {
      var newList = editor.dom.rename(list, listName)
      updateListWithDetails(editor.dom, newList, detail)
      fireListEvent(editor, listToggleActionFromListName(listName), newList)
    } else {
      updateListWithDetails(editor.dom, list, detail)
      fireListEvent(editor, listToggleActionFromListName(listName), list)
    }
  }
  var toggleMultipleLists = function(editor, parentList, lists, listName, detail) {
    var parentIsList = isListNode(parentList)
    if (parentIsList && parentList.nodeName === listName && !hasListStyleDetail(detail)) {
      flattenListSelection(editor)
    } else {
      applyList(editor, listName, detail)
      var bookmark = createBookmark(editor.selection.getRng())
      var allLists = parentIsList ? __spreadArray([parentList], lists, true) : lists
      global$2.each(allLists, function(elm) {
        updateList$1(editor, elm, listName, detail)
      })
      editor.selection.setRng(resolveBookmark(bookmark))
    }
  }
  var hasListStyleDetail = function(detail) {
    return 'list-style-type' in detail
  }
  var toggleSingleList = function(editor, parentList, listName, detail) {
    if (parentList === editor.getBody()) {
      return
    }
    if (parentList) {
      if (parentList.nodeName === listName && !hasListStyleDetail(detail) && !isCustomList(parentList)) {
        flattenListSelection(editor)
      } else {
        var bookmark = createBookmark(editor.selection.getRng())
        updateListWithDetails(editor.dom, parentList, detail)
        var newList = editor.dom.rename(parentList, listName)
        mergeWithAdjacentLists(editor.dom, newList)
        editor.selection.setRng(resolveBookmark(bookmark))
        applyList(editor, listName, detail)
        fireListEvent(editor, listToggleActionFromListName(listName), newList)
      }
    } else {
      applyList(editor, listName, detail)
      fireListEvent(editor, listToggleActionFromListName(listName), parentList)
    }
  }
  var toggleList = function(editor, listName, _detail) {
    var parentList = getParentList(editor)
    var selectedSubLists = getSelectedSubLists(editor)
    var detail = isObject(_detail) ? _detail : {}
    if (selectedSubLists.length > 0) {
      toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail)
    } else {
      toggleSingleList(editor, parentList, listName, detail)
    }
  }

  var DOM = global$3.DOM
  var normalizeList = function(dom, list) {
    var parentNode = list.parentNode
    if (parentNode.nodeName === 'LI' && parentNode.firstChild === list) {
      var sibling = parentNode.previousSibling
      if (sibling && sibling.nodeName === 'LI') {
        sibling.appendChild(list)
        if (isEmpty(dom, parentNode)) {
          DOM.remove(parentNode)
        }
      } else {
        DOM.setStyle(parentNode, 'listStyleType', 'none')
      }
    }
    if (isListNode(parentNode)) {
      var sibling = parentNode.previousSibling
      if (sibling && sibling.nodeName === 'LI') {
        sibling.appendChild(list)
      }
    }
  }
  var normalizeLists = function(dom, element) {
    var lists = global$2.grep(dom.select('ol,ul', element))
    global$2.each(lists, function(list) {
      normalizeList(dom, list)
    })
  }

  var findNextCaretContainer = function(editor, rng, isForward, root) {
    var node = rng.startContainer
    var offset = rng.startOffset
    if (isTextNode(node) && (isForward ? offset < node.data.length : offset > 0)) {
      return node
    }
    var nonEmptyBlocks = editor.schema.getNonEmptyElements()
    if (node.nodeType === 1) {
      node = global$6.getNode(node, offset)
    }
    var walker = new global$5(node, root)
    if (isForward) {
      if (isBogusBr(editor.dom, node)) {
        walker.next()
      }
    }
    while (node = walker[isForward ? 'next' : 'prev2']()) {
      if (node.nodeName === 'LI' && !node.hasChildNodes()) {
        return node
      }
      if (nonEmptyBlocks[node.nodeName]) {
        return node
      }
      if (isTextNode(node) && node.data.length > 0) {
        return node
      }
    }
  }
  var hasOnlyOneBlockChild = function(dom, elm) {
    var childNodes = elm.childNodes
    return childNodes.length === 1 && !isListNode(childNodes[0]) && dom.isBlock(childNodes[0])
  }
  var unwrapSingleBlockChild = function(dom, elm) {
    if (hasOnlyOneBlockChild(dom, elm)) {
      dom.remove(elm.firstChild, true)
    }
  }
  var moveChildren = function(dom, fromElm, toElm) {
    var node
    var targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm
    unwrapSingleBlockChild(dom, fromElm)
    if (!isEmpty(dom, fromElm, true)) {
      while (node = fromElm.firstChild) {
        targetElm.appendChild(node)
      }
    }
  }
  var mergeLiElements = function(dom, fromElm, toElm) {
    var listNode
    var ul = fromElm.parentNode
    if (!isChildOfBody(dom, fromElm) || !isChildOfBody(dom, toElm)) {
      return
    }
    if (isListNode(toElm.lastChild)) {
      listNode = toElm.lastChild
    }
    if (ul === toElm.lastChild) {
      if (isBr(ul.previousSibling)) {
        dom.remove(ul.previousSibling)
      }
    }
    var node = toElm.lastChild
    if (node && isBr(node) && fromElm.hasChildNodes()) {
      dom.remove(node)
    }
    if (isEmpty(dom, toElm, true)) {
      dom.$(toElm).empty()
    }
    moveChildren(dom, fromElm, toElm)
    if (listNode) {
      toElm.appendChild(listNode)
    }
    var contains$1 = contains(SugarElement.fromDom(toElm), SugarElement.fromDom(fromElm))
    var nestedLists = contains$1 ? dom.getParents(fromElm, isListNode, toElm) : []
    dom.remove(fromElm)
    each$1(nestedLists, function(list) {
      if (isEmpty(dom, list) && list !== dom.getRoot()) {
        dom.remove(list)
      }
    })
  }
  var mergeIntoEmptyLi = function(editor, fromLi, toLi) {
    editor.dom.$(toLi).empty()
    mergeLiElements(editor.dom, fromLi, toLi)
    editor.selection.setCursorLocation(toLi, 0)
  }
  var mergeForward = function(editor, rng, fromLi, toLi) {
    var dom = editor.dom
    if (dom.isEmpty(toLi)) {
      mergeIntoEmptyLi(editor, fromLi, toLi)
    } else {
      var bookmark = createBookmark(rng)
      mergeLiElements(dom, fromLi, toLi)
      editor.selection.setRng(resolveBookmark(bookmark))
    }
  }
  var mergeBackward = function(editor, rng, fromLi, toLi) {
    var bookmark = createBookmark(rng)
    mergeLiElements(editor.dom, fromLi, toLi)
    var resolvedBookmark = resolveBookmark(bookmark)
    editor.selection.setRng(resolvedBookmark)
  }
  var backspaceDeleteFromListToListCaret = function(editor, isForward) {
    var dom = editor.dom;var selection = editor.selection
    var selectionStartElm = selection.getStart()
    var root = getClosestListRootElm(editor, selectionStartElm)
    var li = dom.getParent(selection.getStart(), 'LI', root)
    if (li) {
      var ul = li.parentNode
      if (ul === editor.getBody() && isEmpty(dom, ul)) {
        return true
      }
      var rng_1 = normalizeRange(selection.getRng())
      var otherLi_1 = dom.getParent(findNextCaretContainer(editor, rng_1, isForward, root), 'LI', root)
      if (otherLi_1 && otherLi_1 !== li) {
        editor.undoManager.transact(function() {
          if (isForward) {
            mergeForward(editor, rng_1, otherLi_1, li)
          } else {
            if (isFirstChild(li)) {
              outdentListSelection(editor)
            } else {
              mergeBackward(editor, rng_1, li, otherLi_1)
            }
          }
        })
        return true
      } else if (!otherLi_1) {
        if (!isForward && rng_1.startOffset === 0 && rng_1.endOffset === 0) {
          editor.undoManager.transact(function() {
            flattenListSelection(editor)
          })
          return true
        }
      }
    }
    return false
  }
  var removeBlock = function(dom, block, root) {
    var parentBlock = dom.getParent(block.parentNode, dom.isBlock, root)
    dom.remove(block)
    if (parentBlock && dom.isEmpty(parentBlock)) {
      dom.remove(parentBlock)
    }
  }
  var backspaceDeleteIntoListCaret = function(editor, isForward) {
    var dom = editor.dom
    var selectionStartElm = editor.selection.getStart()
    var root = getClosestListRootElm(editor, selectionStartElm)
    var block = dom.getParent(selectionStartElm, dom.isBlock, root)
    if (block && dom.isEmpty(block)) {
      var rng = normalizeRange(editor.selection.getRng())
      var otherLi_2 = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root)
      if (otherLi_2) {
        editor.undoManager.transact(function() {
          removeBlock(dom, block, root)
          mergeWithAdjacentLists(dom, otherLi_2.parentNode)
          editor.selection.select(otherLi_2, true)
          editor.selection.collapse(isForward)
        })
        return true
      }
    }
    return false
  }
  var backspaceDeleteCaret = function(editor, isForward) {
    return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward)
  }
  var backspaceDeleteRange = function(editor) {
    var selectionStartElm = editor.selection.getStart()
    var root = getClosestListRootElm(editor, selectionStartElm)
    var startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root)
    if (startListParent || getSelectedListItems(editor).length > 0) {
      editor.undoManager.transact(function() {
        editor.execCommand('Delete')
        normalizeLists(editor.dom, editor.getBody())
      })
      return true
    }
    return false
  }
  var backspaceDelete = function(editor, isForward) {
    return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor)
  }
  var setup$1 = function(editor) {
    editor.on('keydown', function(e) {
      if (e.keyCode === global$4.BACKSPACE) {
        if (backspaceDelete(editor, false)) {
          e.preventDefault()
        }
      } else if (e.keyCode === global$4.DELETE) {
        if (backspaceDelete(editor, true)) {
          e.preventDefault()
        }
      }
    })
  }

  var get = function(editor) {
    return {
      backspaceDelete: function(isForward) {
        backspaceDelete(editor, isForward)
      }
    }
  }

  var updateList = function(editor, update) {
    var parentList = getParentList(editor)
    editor.undoManager.transact(function() {
      if (isObject(update.styles)) {
        editor.dom.setStyles(parentList, update.styles)
      }
      if (isObject(update.attrs)) {
        each(update.attrs, function(v, k) {
          return editor.dom.setAttrib(parentList, k, v)
        })
      }
    })
  }

  var parseAlphabeticBase26 = function(str) {
    var chars = reverse(trim(str).split(''))
    var values = map(chars, function(char, i) {
      var charValue = char.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0) + 1
      return Math.pow(26, i) * charValue
    })
    return foldl(values, function(sum, v) {
      return sum + v
    }, 0)
  }
  var composeAlphabeticBase26 = function(value) {
    value--
    if (value < 0) {
      return ''
    } else {
      var remainder = value % 26
      var quotient = Math.floor(value / 26)
      var rest = composeAlphabeticBase26(quotient)
      var char = String.fromCharCode('A'.charCodeAt(0) + remainder)
      return rest + char
    }
  }
  var isUppercase = function(str) {
    return /^[A-Z]+$/.test(str)
  }
  var isLowercase = function(str) {
    return /^[a-z]+$/.test(str)
  }
  var isNumeric = function(str) {
    return /^[0-9]+$/.test(str)
  }
  var deduceListType = function(start) {
    if (isNumeric(start)) {
      return 2
    } else if (isUppercase(start)) {
      return 0
    } else if (isLowercase(start)) {
      return 1
    } else if (isEmpty$1(start)) {
      return 3
    } else {
      return 4
    }
  }
  var parseStartValue = function(start) {
    switch (deduceListType(start)) {
      case 2:
        return Optional.some({
          listStyleType: Optional.none(),
          start: start
        })
      case 0:
        return Optional.some({
          listStyleType: Optional.some('upper-alpha'),
          start: parseAlphabeticBase26(start).toString()
        })
      case 1:
        return Optional.some({
          listStyleType: Optional.some('lower-alpha'),
          start: parseAlphabeticBase26(start).toString()
        })
      case 3:
        return Optional.some({
          listStyleType: Optional.none(),
          start: ''
        })
      case 4:
        return Optional.none()
    }
  }
  var parseDetail = function(detail) {
    var start = parseInt(detail.start, 10)
    if (is(detail.listStyleType, 'upper-alpha')) {
      return composeAlphabeticBase26(start)
    } else if (is(detail.listStyleType, 'lower-alpha')) {
      return composeAlphabeticBase26(start).toLowerCase()
    } else {
      return detail.start
    }
  }

  var open = function(editor) {
    var currentList = getParentList(editor)
    if (!isOlNode(currentList)) {
      return
    }
    editor.windowManager.open({
      title: 'List Properties',
      body: {
        type: 'panel',
        items: [{
          type: 'input',
          name: 'start',
          label: 'Start list at number',
          inputMode: 'numeric'
        }]
      },
      initialData: {
        start: parseDetail({
          start: editor.dom.getAttrib(currentList, 'start', '1'),
          listStyleType: Optional.some(editor.dom.getStyle(currentList, 'list-style-type'))
        })
      },
      buttons: [
        {
          type: 'cancel',
          name: 'cancel',
          text: 'Cancel'
        },
        {
          type: 'submit',
          name: 'save',
          text: 'Save',
          primary: true
        }
      ],
      onSubmit: function(api) {
        var data = api.getData()
        parseStartValue(data.start).each(function(detail) {
          editor.execCommand('mceListUpdate', false, {
            attrs: { start: detail.start === '1' ? '' : detail.start },
            styles: { 'list-style-type': detail.listStyleType.getOr('') }
          })
        })
        api.close()
      }
    })
  }

  var queryListCommandState = function(editor, listName) {
    return function() {
      var parentList = getParentList(editor)
      return parentList && parentList.nodeName === listName
    }
  }
  var registerDialog = function(editor) {
    editor.addCommand('mceListProps', function() {
      open(editor)
    })
  }
  var register$2 = function(editor) {
    editor.on('BeforeExecCommand', function(e) {
      var cmd = e.command.toLowerCase()
      if (cmd === 'indent') {
        indentListSelection(editor)
      } else if (cmd === 'outdent') {
        outdentListSelection(editor)
      }
    })
    editor.addCommand('InsertUnorderedList', function(ui, detail) {
      toggleList(editor, 'UL', detail)
    })
    editor.addCommand('InsertOrderedList', function(ui, detail) {
      toggleList(editor, 'OL', detail)
    })
    editor.addCommand('InsertDefinitionList', function(ui, detail) {
      toggleList(editor, 'DL', detail)
    })
    editor.addCommand('RemoveList', function() {
      flattenListSelection(editor)
    })
    registerDialog(editor)
    editor.addCommand('mceListUpdate', function(ui, detail) {
      if (isObject(detail)) {
        updateList(editor, detail)
      }
    })
    editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'))
    editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'))
    editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'))
  }

  var setupTabKey = function(editor) {
    editor.on('keydown', function(e) {
      if (e.keyCode !== global$4.TAB || global$4.metaKeyPressed(e)) {
        return
      }
      editor.undoManager.transact(function() {
        if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) {
          e.preventDefault()
        }
      })
    })
  }
  var setup = function(editor) {
    if (shouldIndentOnTab(editor)) {
      setupTabKey(editor)
    }
    setup$1(editor)
  }

  var register$1 = function(editor) {
    var exec = function(command) {
      return function() {
        return editor.execCommand(command)
      }
    }
    if (!editor.hasPlugin('advlist')) {
      editor.ui.registry.addToggleButton('numlist', {
        icon: 'ordered-list',
        active: false,
        tooltip: 'Numbered list',
        onAction: exec('InsertOrderedList'),
        onSetup: function(api) {
          return listState(editor, 'OL', api.setActive)
        }
      })
      editor.ui.registry.addToggleButton('bullist', {
        icon: 'unordered-list',
        active: false,
        tooltip: 'Bullet list',
        onAction: exec('InsertUnorderedList'),
        onSetup: function(api) {
          return listState(editor, 'UL', api.setActive)
        }
      })
    }
  }

  var register = function(editor) {
    var listProperties = {
      text: 'List properties...',
      icon: 'ordered-list',
      onAction: function() {
        return editor.execCommand('mceListProps')
      },
      onSetup: function(api) {
        return listState(editor, 'OL', function(active) {
          return api.setDisabled(!active)
        })
      }
    }
    editor.ui.registry.addMenuItem('listprops', listProperties)
    editor.ui.registry.addContextMenu('lists', {
      update: function(node) {
        var parentList = getParentList(editor, node)
        return isOlNode(parentList) ? ['listprops'] : []
      }
    })
  }

  function Plugin() {
    global$7.add('lists', function(editor) {
      if (editor.hasPlugin('rtc', true) === false) {
        setup(editor)
        register$2(editor)
      } else {
        registerDialog(editor)
      }
      register$1(editor)
      register(editor)
      return get(editor)
    })
  }

  Plugin()
}())
